package com.boot.cluster.worker;

import com.boot.cluster.worker.bean.TaskResponse;
import com.boot.cluster.worker.bean.TaskRunner;
import com.boot.cluster.worker.bean.TaskSplitterInfo;
import com.boot.cluster.worker.bean.TaskWrap;
import com.boot.cluster.worker.runner.Combiner;
import io.micrometer.core.instrument.util.NamedThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.retry.support.RetryTemplate;

import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class LocalScheduler {

	private static Logger logger = LoggerFactory.getLogger(LocalScheduler.class);

	protected RetryTemplate retryTemplate = new RetryTemplate();

	/***暂时设置任务的最大超时时间 ***/
	protected Long timeout=30*60*1000L;
	protected ThreadPoolExecutor executor= new ThreadPoolExecutor(1, 100, 60, TimeUnit.SECONDS,
			new LinkedBlockingQueue<Runnable>(),
			new NamedThreadFactory("actor-thread-pool"));
	private Actor actor;

	public LocalScheduler() {
		this.actor = new Actor(this.executor);
	}


	public LocalScheduler(ThreadPoolExecutor executor) {
		this.actor = new Actor(executor);
	}

	protected <T> T combiner(List<TaskResponse> list, Class<? extends Combiner> cls){
		if((list==null) || list.isEmpty()||(cls==null)) {
			return null;
		}
		try {
			Combiner cb = cls.newInstance();
			return cb.action(list);
		} catch (Exception e) {
			logger.error("",e);
		}
		return null;
	}


	public List<TaskResponse> submit(TaskWrap wrap){
		if((wrap==null) ||(wrap.getTasks()==null)||wrap.getTasks().isEmpty()) {
			return null;
		}
		List<TaskResponse> res = this.actor.submit(wrap.getTasks(), wrap.getRunner());

		if(!res.isEmpty()) {
			this.combiner(res, wrap.getRunner().getCbls());
		}
		return res;
	}

	public void cancelTask(TaskRunner runner, TaskSplitterInfo info) {
		this.actor.cancelTask(runner, info);
	}

	public void cancelAllTask(TaskRunner runner,List<TaskSplitterInfo> infos) {
		this.actor.cancelAllTask(runner, infos);
	}
	public void cancelAllTask(TaskWrap wrap) {
		this.actor.cancelAllTask(wrap.getRunner(),wrap.getTasks());
	}
}
